package com.ganzalang.gmall.command.inventory.updater;

import com.ganzalang.gmall.command.api.dto.IncreaseInventoryDTO;
import com.ganzalang.gmall.command.api.dto.SubOrderVariantDTO;
import com.ganzalang.gmall.command.constants.InventoryLogConstants;
import com.ganzalang.gmall.command.domain.ProductVariantInventory;
import com.ganzalang.gmall.command.domain.ProductVariantInventoryLog;
import com.ganzalang.gmall.command.enums.InventoryLogEventEnum;
import com.ganzalang.gmall.command.service.ProductVariantInventoryService;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @program: saas-shoplus-product-parent
 * @description: 锁定库存,增加锁定库存,减少可用库存
 * @author: jingyang
 * @create: 2020-08-13 14:29
 **/
public class LockSaleInventoryUpdater extends AbstractInventoryUpdater{

    /**
     * 用户下单对应商品的DTO对象
     */
    private Map<Long, SubOrderVariantDTO> subOrderVariantDTOMap;

    /**
     * 预扣库存成功的skuID
     */
    private List<SubOrderVariantDTO> withholdingDecreaseInventorySuccessVariantList;

    /**
     * 构造方法
     * @param inventoryService 商品库存service组件
     * @param productVariantInventories 商品库存DO对
     * @param subOrderVariantDTOMap 用户下单对应商品的DTO对象Map,key:skuId,value:对应的数量
     */
    public LockSaleInventoryUpdater(
            ProductVariantInventoryService inventoryService,
            List<ProductVariantInventory> productVariantInventories,
            Map<Long,SubOrderVariantDTO> subOrderVariantDTOMap,
            ApplicationEventPublisher publisher,
            Long shopId) {
        super(inventoryService, productVariantInventories, publisher, shopId);
        this.subOrderVariantDTOMap = subOrderVariantDTOMap;
        this.withholdingDecreaseInventorySuccessVariantList = new ArrayList<>(subOrderVariantDTOMap.size());
    }

    /**
     * 更新可用库存
     */
    @Override
    protected void updateAvailableInventory() {
        for (ProductVariantInventory inventory : productVariantInventories) {
            SubOrderVariantDTO subOrderVariantDTO = subOrderVariantDTOMap.get(inventory.getSkuId());
            //循环减库存,如果其中一个扣减失败,则回滚之前的库存
            Boolean isSuccess = inventoryService.withholdingDecreaseInventory(
                    subOrderVariantDTO.getShopId(),
                    subOrderVariantDTO.getSpuId(),
                    subOrderVariantDTO.getSkuId(),
                    subOrderVariantDTO.getQuantity());
            //如果扣减失败,则抛出异常
//            CommonAssertUtil.assertTrue(isSuccess,
//                    ShoplusProductException.DECREASE_INVENTORY_ERROR.format(subOrderVariantDTO.getVariantId()));
            withholdingDecreaseInventorySuccessVariantList.add(subOrderVariantDTO);
            inventory.setAvailableStockQuantity(-subOrderVariantDTO.getQuantity());
        }
    }

    /**
     * 更新锁定库存
     */
    @Override
    protected void updateLockInventory() {
        for (ProductVariantInventory inventory : productVariantInventories) {
            SubOrderVariantDTO subOrderVariantDTO = subOrderVariantDTOMap.get(inventory.getSkuId());
            for (ProductVariantInventory productVariantInventory : productVariantInventories) {
                productVariantInventory.setLockedStockQuantity(subOrderVariantDTO.getQuantity());
            }
        }
    }

    /**
     * 更新库存日志表
     */
    @Override
    protected void updateInventoryLog() {
        productVariantInventoryLogs = new ArrayList<>(productVariantInventories.size());
        for (ProductVariantInventory inventory : productVariantInventories) {
            SubOrderVariantDTO subOrderVariantDTO = subOrderVariantDTOMap.get(inventory.getSkuId());
            ProductVariantInventoryLog log = new ProductVariantInventoryLog();
            log.setSpuId(inventory.getSpuId());
            log.setSkuId(subOrderVariantDTO.getSkuId());
            log.setChangStockQuantity(-subOrderVariantDTO.getQuantity());
            log.setAvailableStockQuantity(inventory.getAvailableStockQuantity());
            productVariantInventoryLogs.add(log);
        }
    }

    /**
     * 回滚操作
     */
    @Override
    protected void rollback() {
        if(!CollectionUtils.isEmpty(withholdingDecreaseInventorySuccessVariantList)){
            //批量回滚已经扣减的sku库存
            List<IncreaseInventoryDTO> increaseInventoryDTOS = withholdingDecreaseInventorySuccessVariantList.stream()
                    .map(subOrderVariantDTO -> subOrderVariantDTO.clone(IncreaseInventoryDTO.class))
                    .collect(Collectors.toList());
            inventoryService.rollbackWithholdingDecreaseInventory(increaseInventoryDTOS);
        }
    }

}
